package com.example.projectmanagement.service;

import com.example.projectmanagement.dto.UserDto;
import com.example.projectmanagement.dto.UserUpdateDto;
import com.example.projectmanagement.dto.UserProfileDto;
import com.example.projectmanagement.model.User;
import com.example.projectmanagement.model.Role;
import com.example.projectmanagement.repository.UserRepository;
import com.example.projectmanagement.repository.UserRoleRepository;
import com.example.projectmanagement.util.FileSecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private UserRoleRepository userRoleRepository;
    
    @Autowired
    private com.example.projectmanagement.repository.RoleRepository roleRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 获取用户分页列表
     */
    public Page<User> getUsers(int page, int size, String name, String username, Integer status) {
        Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createTime"));
        
        if (name != null && !name.isEmpty()) {
            if (username != null && !username.isEmpty()) {
                if (status != null) {
                    return userRepository.findByNameContainingAndUsernameContainingAndStatus(name, username, status, pageable);
                } else {
                    return userRepository.findByNameContainingAndUsernameContaining(name, username, pageable);
                }
            } else {
                if (status != null) {
                    return userRepository.findByNameContainingAndStatus(name, status, pageable);
                } else {
                    return userRepository.findByNameContaining(name, pageable);
                }
            }
        } else if (username != null && !username.isEmpty()) {
            if (status != null) {
                return userRepository.findByUsernameContainingAndStatus(username, status, pageable);
            } else {
                return userRepository.findByUsernameContaining(username, pageable);
            }
        } else if (status != null) {
            return userRepository.findByStatus(status, pageable);
        } else {
            return userRepository.findAll(pageable);
        }
    }

    /**
     * 根据ID获取用户
     */
    public Optional<User> getUserById(Long id) {
        return userRepository.findById(id);
    }

    /**
     * 创建用户
     */
    @Transactional
    public User createUser(UserDto userDto) {
        User user = new User();
        user.setUsername(userDto.getUsername());
        user.setName(userDto.getName());
        user.setPhone(userDto.getPhone());
        user.setDepartment(userDto.getDepartment());
        user.setStatus(userDto.getStatus());
        user.setRole(userDto.getRole());
        
        // 密码加密
        if (userDto.getPassword() != null && !userDto.getPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(userDto.getPassword()));
        } else {
            // 为新注册用户设置默认密码
            user.setPassword(passwordEncoder.encode("123456"));
        }
        
        User savedUser = userRepository.save(user);
        
        // 创建用户角色关联（避免重复）
        Optional<Role> roleOpt = roleRepository.findByRoleName(userDto.getRole());
        if (roleOpt.isPresent()) {
            // 检查是否已存在用户角色关联
            boolean exists = userRoleRepository.existsByUser_IdAndRole_Id(savedUser.getId(), roleOpt.get().getId());
            if (!exists) {
                com.example.projectmanagement.model.UserRole userRole = new com.example.projectmanagement.model.UserRole();
                userRole.setUser(savedUser);
                userRole.setRole(roleOpt.get());
                userRoleRepository.save(userRole);
                System.out.println("User role association created for user: " + savedUser.getUsername() + ", role: " + roleOpt.get().getRoleName());
            } else {
                System.out.println("User role association already exists for user: " + savedUser.getUsername() + ", role: " + roleOpt.get().getRoleName());
            }
        } else {
            System.out.println("Role not found for user: " + savedUser.getUsername() + ", role: " + userDto.getRole());
        }
        
        return savedUser;
    }

    /**
     * 更新用户
     */
    public User updateUser(Long id, UserDto userDto) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));
        
        // 只有当用户名不为空时才进行检查和更新
        if (userDto.getUsername() != null && !userDto.getUsername().trim().isEmpty()) {
            // 更完善的用户名唯一性检查
            if (!user.getUsername().equals(userDto.getUsername())) {
                // 只有当用户名真正改变时才检查唯一性，并且排除当前用户ID
                Optional<User> existingUser = userRepository.findByUsername(userDto.getUsername());
                if (existingUser.isPresent() && !existingUser.get().getId().equals(id)) {
                    throw new RuntimeException("用户名已存在");
                }
            }
            user.setUsername(userDto.getUsername());
        }
        
        // 只有当姓名不为空时才更新
        if (userDto.getName() != null && !userDto.getName().trim().isEmpty()) {
            user.setName(userDto.getName());
        }
        
        // 只有当电话不为空时才更新
        if (userDto.getPhone() != null && !userDto.getPhone().trim().isEmpty()) {
            user.setPhone(userDto.getPhone());
        } else if (userDto.getPhone() == null) {
            user.setPhone(null);
        }
        
        // 只有当部门不为空时才更新
        if (userDto.getDepartment() != null && !userDto.getDepartment().trim().isEmpty()) {
            user.setDepartment(userDto.getDepartment());
        } else if (userDto.getDepartment() == null) {
            user.setDepartment(null);
        }
        
        // 只有当状态不为null时才更新
        if (userDto.getStatus() != null) {
            user.setStatus(userDto.getStatus());
        }
        
        // 只有当角色不为空时才更新
        if (userDto.getRole() != null && !userDto.getRole().trim().isEmpty()) {
            user.setRole(userDto.getRole());
            // 更新用户角色关联
            Optional<Role> roleOpt = roleRepository.findByRoleName(userDto.getRole());
            if (roleOpt.isPresent()) {
                // 检查是否已存在相同的用户角色关联
                boolean exists = userRoleRepository.existsByUser_IdAndRole_Id(user.getId(), roleOpt.get().getId());
                if (!exists) {
                    // 删除旧的角色关联
                    userRoleRepository.deleteByUser_Id(user.getId());
                    // 创建新的角色关联
                    com.example.projectmanagement.model.UserRole userRole = new com.example.projectmanagement.model.UserRole();
                    userRole.setUser(user);
                    userRole.setRole(roleOpt.get());
                    userRoleRepository.save(userRole);
                    System.out.println("User role association updated for user: " + user.getUsername() + ", role: " + roleOpt.get().getRoleName());
                } else {
                    System.out.println("User role association already exists for user: " + user.getUsername() + ", role: " + roleOpt.get().getRoleName());
                }
            } else {
                System.out.println("Role not found for user: " + user.getUsername() + ", role: " + userDto.getRole());
            }
        }
        
        // 如果提供了新密码，则更新密码
        if (userDto.getPassword() != null && !userDto.getPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(userDto.getPassword()));
        }
        
        return userRepository.save(user);
    }
    
    /**
     * 更新用户（用于部分更新）
     */
    @Transactional
    public User updateUser(Long id, UserUpdateDto userUpdateDto) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));
        
        // 只有当用户名不为空时才进行检查和更新
        if (userUpdateDto.getUsername() != null && !userUpdateDto.getUsername().trim().isEmpty()) {
            // 更完善的用户名唯一性检查
            if (!user.getUsername().equals(userUpdateDto.getUsername())) {
                // 只有当用户名真正改变时才检查唯一性，并且排除当前用户ID
                Optional<User> existingUser = userRepository.findByUsername(userUpdateDto.getUsername());
                if (existingUser.isPresent() && !existingUser.get().getId().equals(id)) {
                    throw new RuntimeException("用户名已存在");
                }
            }
            user.setUsername(userUpdateDto.getUsername());
        }
        
        // 只有当姓名不为空时才更新
        if (userUpdateDto.getName() != null && !userUpdateDto.getName().trim().isEmpty()) {
            user.setName(userUpdateDto.getName());
        }
        
        // 只有当电话不为空时才更新
        if (userUpdateDto.getPhone() != null && !userUpdateDto.getPhone().trim().isEmpty()) {
            user.setPhone(userUpdateDto.getPhone());
        } else if (userUpdateDto.getPhone() == null) {
            user.setPhone(null);
        }
        
        // 只有当部门不为空时才更新
        if (userUpdateDto.getDepartment() != null && !userUpdateDto.getDepartment().trim().isEmpty()) {
            user.setDepartment(userUpdateDto.getDepartment());
        } else if (userUpdateDto.getDepartment() == null) {
            user.setDepartment(null);
        }
        
        // 只有当状态不为null时才更新（仅管理员可以修改）
        if (userUpdateDto.getStatus() != null) {
            // 这里应该检查调用者是否为管理员，但为了简化，我们在Controller层控制
            user.setStatus(userUpdateDto.getStatus());
        }
        
        // 只有当角色不为空时才更新（仅管理员可以修改）
        if (userUpdateDto.getRole() != null && !userUpdateDto.getRole().trim().isEmpty()) {
            // 这里应该检查调用者是否为管理员，但为了简化，我们在Controller层控制
            user.setRole(userUpdateDto.getRole());
            // 更新用户角色关联
            Optional<Role> roleOpt = roleRepository.findByRoleName(userUpdateDto.getRole());
            if (roleOpt.isPresent()) {
                // 检查是否已存在相同的用户角色关联
                boolean exists = userRoleRepository.existsByUser_IdAndRole_Id(user.getId(), roleOpt.get().getId());
                if (!exists) {
                    // 删除旧的角色关联
                    userRoleRepository.deleteByUser_Id(user.getId());
                    // 创建新的角色关联
                    com.example.projectmanagement.model.UserRole userRole = new com.example.projectmanagement.model.UserRole();
                    userRole.setUser(user);
                    userRole.setRole(roleOpt.get());
                    userRoleRepository.save(userRole);
                    System.out.println("User role association updated for user: " + user.getUsername() + ", role: " + roleOpt.get().getRoleName());
                } else {
                    System.out.println("User role association already exists for user: " + user.getUsername() + ", role: " + roleOpt.get().getRoleName());
                }
            } else {
                System.out.println("Role not found for user: " + user.getUsername() + ", role: " + userUpdateDto.getRole());
            }
        }
        
        // 如果提供了新密码，则更新密码
        if (userUpdateDto.getPassword() != null && !userUpdateDto.getPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(userUpdateDto.getPassword()));
        }
        
        // 如果提供了头像，则更新头像
        if (userUpdateDto.getAvatar() != null && !userUpdateDto.getAvatar().isEmpty()) {
            // 检查头像数据长度，如果太长则截断以避免数据库错误
            String avatarData = userUpdateDto.getAvatar();
            // 使用更保守的长度限制，确保兼容性
            if (avatarData.length() > 1000000) { // 限制在1MB以内
                // 如果数据太长，记录警告并跳过更新
                System.out.println("Avatar data too long, skipping update. Length: " + avatarData.length());
            } else {
                user.setAvatar(avatarData);
            }
        }
        
        return userRepository.save(user);
    }
    
    /**
     * 当前用户更新自己的信息（安全版本）
     */
    @Transactional
    public User updateCurrentUserInfo(Long id, UserUpdateDto userUpdateDto) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));
        
        // 当前用户只能更新以下字段，不能更新角色和状态等敏感字段
        // 只有当姓名不为空时才更新
        if (userUpdateDto.getName() != null && !userUpdateDto.getName().trim().isEmpty()) {
            user.setName(userUpdateDto.getName());
        }
        
        // 只有当电话不为空时才更新
        if (userUpdateDto.getPhone() != null && !userUpdateDto.getPhone().trim().isEmpty()) {
            user.setPhone(userUpdateDto.getPhone());
        } else if (userUpdateDto.getPhone() == null) {
            user.setPhone(null);
        }
        
        // 只有当部门不为空时才更新
        if (userUpdateDto.getDepartment() != null && !userUpdateDto.getDepartment().trim().isEmpty()) {
            user.setDepartment(userUpdateDto.getDepartment());
        } else if (userUpdateDto.getDepartment() == null) {
            user.setDepartment(null);
        }
        
        // 如果提供了头像，则更新头像
        if (userUpdateDto.getAvatar() != null && !userUpdateDto.getAvatar().isEmpty()) {
            // 检查头像数据长度，如果太长则截断以避免数据库错误
            String avatarData = userUpdateDto.getAvatar();
            // 使用更保守的长度限制，确保兼容性
            if (avatarData.length() > 1000000) { // 限制在1MB以内
                // 如果数据太长，记录警告并跳过更新
                System.out.println("Avatar data too long, skipping update. Length: " + avatarData.length());
            } else {
                user.setAvatar(avatarData);
            }
        }
        
        // 确保不会更新敏感字段
        userUpdateDto.setRole(null);
        userUpdateDto.setStatus(null);
        userUpdateDto.setPassword(null);
        
        return userRepository.save(user);
    }

    /**
     * 更新用户状态
     */
    public User updateUserStatus(Long id, Integer status) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));
        
        user.setStatus(status);
        return userRepository.save(user);
    }
    
    /**
     * 更新用户密码（管理员功能）
     */
    public User updateUserPassword(Long id, String newPassword) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));
        
        user.setPassword(passwordEncoder.encode(newPassword));
        return userRepository.save(user);
    }
    
    /**
     * 当前用户修改自己的密码
     */
    public User updateCurrentUserPassword(Long id, String currentPassword, String newPassword) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));
        
        // 验证当前密码是否正确
        if (!passwordEncoder.matches(currentPassword, user.getPassword())) {
            throw new RuntimeException("当前密码不正确");
        }
        
        // 更新密码
        user.setPassword(passwordEncoder.encode(newPassword));
        return userRepository.save(user);
    }

    /**
     * 删除用户
     */
    @Transactional
    public void deleteUser(Long id) {
        // 先删除用户角色关联
        userRoleRepository.deleteByUser_Id(id);
        // 再删除用户
        userRepository.deleteById(id);
    }

    /**
     * 检查用户名是否存在
     */
    public boolean existsByUsername(String username) {
        return userRepository.existsByUsername(username);
    }
    
    /**
     * 根据用户名获取用户
     */
    public Optional<User> getUserByUsername(String username) {
        return userRepository.findByUsername(username);
    }
    
    /**
     * 获取用户的所有角色
     */
    public List<Role> getUserRoles(Long userId) {
        return userRoleRepository.findRolesByUserId(userId);
    }
    
    /**
     * 更新用户头像路径
     */
    public void updateUserAvatar(Long id, String avatarPath) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));
        
        // 验证头像路径安全性
        if (avatarPath != null && !avatarPath.isEmpty()) {
            if (!isValidAvatarPath(avatarPath)) {
                throw new RuntimeException("无效的头像路径");
            }
        }
        
        user.setAvatar(avatarPath);
        userRepository.save(user);
    }
    
    /**
     * 更新用户学习档案
     */
    @Transactional
    public User updateUserProfile(Long id, UserProfileDto profileDto) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));
        
        // 更新基本信息（继承自UserUpdateDto）
        if (profileDto.getName() != null && !profileDto.getName().trim().isEmpty()) {
            user.setName(profileDto.getName());
        }
        
        if (profileDto.getPhone() != null && !profileDto.getPhone().trim().isEmpty()) {
            user.setPhone(profileDto.getPhone());
        } else if (profileDto.getPhone() == null) {
            user.setPhone(null);
        }
        
        if (profileDto.getDepartment() != null && !profileDto.getDepartment().trim().isEmpty()) {
            user.setDepartment(profileDto.getDepartment());
        } else if (profileDto.getDepartment() == null) {
            user.setDepartment(null);
        }
        
        // 更新学习档案特定字段
        if (profileDto.getNickname() != null) {
            user.setNickname(profileDto.getNickname());
        }
        
        if (profileDto.getGender() != null) {
            user.setGender(profileDto.getGender());
        }
        
        if (profileDto.getBirthDate() != null && !profileDto.getBirthDate().isEmpty()) {
            try {
                LocalDateTime birthDate = LocalDateTime.parse(profileDto.getBirthDate(), DateTimeFormatter.ISO_LOCAL_DATE_TIME);
                user.setBirthDate(birthDate);
            } catch (Exception e) {
                // 如果日期格式不正确，忽略该字段的更新
            }
        }
        
        if (profileDto.getBio() != null) {
            user.setBio(profileDto.getBio());
        }
        
        // 注意：学习积分和学习等级由系统自动管理，不由用户直接更新
        // 如果需要更新这些字段，应该通过专门的积分管理系统
        
        return userRepository.save(user);
    }
    
    /**
     * 验证头像路径安全性
     * @param avatarPath 头像路径
     * @return 是否安全
     */
    private boolean isValidAvatarPath(String avatarPath) {
        return FileSecurityUtil.isValidAvatarPath(avatarPath);
    }
    
    /**
     * 检查用户是否具有指定角色
     */
    public boolean hasRole(User user, String roleName) {
        List<Role> roles = getUserRoles(user.getId());
        return roles.stream()
                .anyMatch(role -> role.getRoleName().equals(roleName));
    }

    public Page<User> searchStudents(String keyword, Pageable pageable) {
        return userRepository.searchStudents(keyword, pageable);
    }

    public Page<User> getAllStudents(Pageable pageable) {
        return userRepository.findAllStudentsOrderByStudyPointsDesc(pageable);
    }
}